//+------------------------------------------------------------------+
//| K 线形态趋势交易策略                                             |
//+------------------------------------------------------------------+
#property copyright "Your Name"
#property link      "Your Website"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>
CTrade trade;

input int      FastMAPeriod = 5;          // 快线周期
input int      SlowMAPeriod = 10;         // 慢线周期
input double   Lots = 0.01;                 // 交易手数
input int      StopLossPoints = 100;       // 止损点数
input int      TakeProfitPoints = 200;     // 止盈点数
input ulong    MagicNumber = 12345;       // EA魔术号


int ssfastMA, fastMA, slowMA;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   fastMA = iMA(_Symbol, PERIOD_CURRENT, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   slowMA = iMA(_Symbol, PERIOD_CURRENT, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   trade.SetExpertMagicNumber(MagicNumber);
   return(INIT_SUCCEEDED);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
  
  
   // 获取均线值
   double  fastMAValues[3], slowMAValues[3];
   //CopyBuffer(ssfastMA, 0, 1, 2, ssfastMAValues);
   CopyBuffer(fastMA, 0, 1, 2, fastMAValues);
   CopyBuffer(slowMA, 0, 1, 2, slowMAValues);
   ArraySetAsSeries(fastMAValues, true);
   ArraySetAsSeries(slowMAValues, true);
   
   
   // 检查交叉信号
  // bool goldenCross = (fastMAValues[1] > slowMAValues[1]) && (fastMAValues[0] <= slowMAValues[0]);
  // bool deathCross = (fastMAValues[1] < slowMAValues[1]) && (fastMAValues[0] >= slowMAValues[0]);
  
  
   if(IsMorningStar())
     {
     // CloseAllPositions();  // 平掉所有仓位
     // OpenBuyPosition();
     }
   if(IsEveningStar())
     {
      CloseAllPositions();  // 平掉所有仓位
      OpenSellPosition();
     }
  }
//+------------------------------------------------------------------+
//| 判断是否为早晨之星                                               |
//+------------------------------------------------------------------+
bool IsMorningStar()
  {
   double open1 = iOpen(Symbol(), 0, 2);
   double close1 = iClose(Symbol(), 0, 2);
   double open2 = iOpen(Symbol(), 0, 1);
   double close2 = iClose(Symbol(), 0, 1);
   double open3 = iOpen(Symbol(), 0, 0);
   double close3 = iClose(Symbol(), 0, 0);

   // 第一根 K 线为大阴线
   if(close1 < open1 && (open1 - close1) > (iHigh(Symbol(), 0, 2) - iLow(Symbol(), 0, 2)) * 0.6)
     {
      // 第二根 K 线为小阴线或小阳线
      if(MathAbs(open2 - close2) < (iHigh(Symbol(), 0, 1) - iLow(Symbol(), 0, 1)) * 0.3)
        {
         // 第三根 K 线为大阳线
         if(close3 > open3 && (close3 - open3) > (iHigh(Symbol(), 0, 0) - iLow(Symbol(), 0, 0)) * 0.6 && close3 > open1)
           {
            return true;
           }
        }
     }
   return false;
  }
//+------------------------------------------------------------------+
//| 判断是否为黄昏之星                                               |
//+------------------------------------------------------------------+
bool IsEveningStar()
  {
   double open1 = iOpen(Symbol(), 0, 2);
   double close1 = iClose(Symbol(), 0, 2);
   double open2 = iOpen(Symbol(), 0, 1);
   double close2 = iClose(Symbol(), 0, 1);
   double open3 = iOpen(Symbol(), 0, 0);
   double close3 = iClose(Symbol(), 0, 0);

   // 第一根 K 线为大阳线
   if(close1 > open1 && (close1 - open1) > (iHigh(Symbol(), 0, 2) - iLow(Symbol(), 0, 2)) * 0.6)
     {
      // 第二根 K 线为小阴线或小阳线
      if(MathAbs(open2 - close2) < (iHigh(Symbol(), 0, 1) - iLow(Symbol(), 0, 1)) * 0.3)
        {
         // 第三根 K 线为大阴线
         if(close3 < open3 && (open3 - close3) > (iHigh(Symbol(), 0, 0) - iLow(Symbol(), 0, 0)) * 0.6 && close3 < open1)
           {
            return true;
           }
        }
     }
   return false;
  }
  
  
//+------------------------------------------------------------------+
//| 开多单（增加持仓检查）                                           |
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
   // 检查是否已有持仓
   if(PositionSelect(_Symbol)) return;

   double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double sl = price - StopLossPoints * _Point;
   double tp = price + TakeProfitPoints * _Point;
   
   trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, Lots, price, sl, tp, "Golden Cross Entry");
}

//+------------------------------------------------------------------+
//| 开空单（增加持仓检查）                                           |
//+------------------------------------------------------------------+
void OpenSellPosition()
{
   // 检查是否已有持仓
   if(PositionSelect(_Symbol)) return;

   double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double sl = price + StopLossPoints * _Point;
   double tp = price - TakeProfitPoints * _Point;
   
   trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, price, sl, tp, "Death Cross Entry");
}

void CloseAllPositions()
{
   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetString(POSITION_SYMBOL) == _Symbol && 
         PositionGetInteger(POSITION_MAGIC) == MagicNumber)
      {
         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         double currentSL = PositionGetDouble(POSITION_SL);
         double currentTP = PositionGetDouble(POSITION_TP);
         double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double requiredPrice = openPrice + openPrice * 0.5;
        
         if(currentPrice/openPrice >=1){
              double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
              double sl = price + 10 * _Point;
              double tp = price - TakeProfitPoints * _Point;
              trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, price, sl, tp, "Death Cross Entry");
          }
   
         if(currentPrice/requiredPrice >=1.5)
         {
            trade.PositionClose(ticket);
         }
      }
   }
}


void CheckTrailingStop()
{
   if(!PositionSelect(_Symbol)) return;

   double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
   double currentSL = PositionGetDouble(POSITION_SL);
   double currentTP = PositionGetDouble(POSITION_TP);
   ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

   if(type == POSITION_TYPE_BUY)
   {
      double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double requiredPrice = openPrice + (TakeProfitPoints * _Point) * 0.5;
      
      if(currentPrice >= requiredPrice && currentSL < openPrice)
      {
         trade.PositionModify(PositionGetInteger(POSITION_TICKET), openPrice, currentTP);
      }
   }
   else if(type == POSITION_TYPE_SELL)
   {
      double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double requiredPrice = openPrice - (TakeProfitPoints * _Point) * 0.5;
      
      if(currentPrice <= requiredPrice && currentSL > openPrice)
      {
         trade.PositionModify(PositionGetInteger(POSITION_TICKET), openPrice, currentTP);
      }
   }
}   